﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ESSManageService.Common.Helper;
using ESSManageService.Enum.WebsocketEnum;
using ESSManageService.Model.WebsocketModels;
using ESSManageService.Serilog;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using WebSocketSharp;

namespace ESSManageService.Services.BusinessServices
{
    /// <summary>
    /// websocket 客户端服务
    /// </summary>
    public class ClientWebSocketService
    {
        #region fields
        private readonly ILogger<ClientWebSocketService> _logger;
        private WebSocket _webSocket;
        private Uri _serverUri;
        /// <summary>
        /// 接收事件传出
        /// </summary>
        public event Action<object, MessageEventArgs> OnReceivedMessage;
        public bool IsConnected { get; private set; } = false;
        private CancellationTokenSource _cancellationTokenSource;
        private DateTime _lastReviceBeatTime = DateTime.Now.AddSeconds(-30);
        #endregion

        #region method
        public ClientWebSocketService(ILogger<ClientWebSocketService> logger)
        {
            _logger = logger;
            _serverUri = new Uri(AppSettings.GetValue("SimulateWebsocketConnectionString").ToString());
            Init();
            _cancellationTokenSource = new CancellationTokenSource();
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("WebSocket 客户端服务正在启动...");
            //SeriLogger.WriteLogInfo("WebSocket 客户端服务正在启动...");
            Connect();
        }

        private void ClientSimulate_OnReceivedMessage(object? sender, MessageEventArgs e)
        {
            _logger.LogDebug($"模拟服务返回数据：{e.Data}");
            OnReceivedMessage?.Invoke(this, e);
            var data = e?.Data;
            try
            {
                var DataInfo = JsonConvert.DeserializeObject<WebSocketMessageBase<object>>(data);

                switch (DataInfo?.Code)
                {
                    case DataCommonEnum.HeatBeat:
                        UpdateLastTime();
                        break;
                    case DataCommonEnum.ManagerSimulateData:
                        //模型数据不需要解析不需要返回，直接入库

                        break;
                    case DataCommonEnum.ManagerServiceStatus:
                        //模拟服务和各个服务之间的通信状态，不需要返回，保存缓存
                        
                        break;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"WebSocket客户端处理数据错误：{ex.GetBaseException().ToString()}");
            }
        }
        /// <summary>
        /// 初始化链接信息
        /// </summary>
        private void Init()
        {
            try
            {
                if (_webSocket != null)
                {
                    _webSocket.OnMessage -= ClientSimulate_OnReceivedMessage;
                    _webSocket.Close();
                    _webSocket = null;
                }
                _webSocket = new WebSocket(_serverUri.ToString());
                _webSocket.OnMessage += ClientSimulate_OnReceivedMessage;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"初始化WebSocket 服务器时出错");
            }
        }
        /// <summary>
        /// 链接服务器
        /// </summary>
        public void Connect()
        {
            try
            {
                if (_webSocket == null)
                    Init();
                IsConnected = false;
                //_webSocket?.ConnectAsync();
                _webSocket?.Connect();

                if (_webSocket != null && _webSocket.IsAlive && _webSocket.ReadyState == WebSocketState.Open)
                {
                    _lastReviceBeatTime = DateTime.Now;
                    IsConnected = true;
                }
            }
            catch (Exception ex)
            {
                IsConnected = false;
            }
            finally
            {
                StartReConnectTask();
            }
        }

        bool taskFlagForAuthorize = false;
        /// <summary>
        /// 重连
        /// </summary>
        private void StartReConnectTask()
        {
            if (taskFlagForAuthorize)
                return;
            taskFlagForAuthorize = true;
            try
            {
                Task.Run(async () =>
                {
                    while (taskFlagForAuthorize)
                    {
                        Thread.Sleep(2 * 1000);
                        try
                        {
                            if ((DateTime.Now - _lastReviceBeatTime).TotalSeconds > 6)
                            {
                                _logger.LogInformation($"{_webSocket.Url}:接收服务器心跳超时");
                                IsConnected = false;
                            }
                            if (!IsConnected)
                            {
                                Connect();
                                _logger.LogInformation("ClientWebSocket尝试重连");
                            } 
                            else
                                SendHeartBeat(); // 发送心跳
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError("重连服务失败：", ex);
                            await Task.Delay(5000, _cancellationTokenSource.Token);
                            continue;
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                _logger.LogInformation("WebSocket服务，向客户端发送心跳失败" + ex.Message);
            }
        }

        public void UpdateLastTime()
        {
            _lastReviceBeatTime = DateTime.Now;
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("WebSocket 客户端服务正在停止...");
            _cancellationTokenSource.Cancel();
            if (_webSocket.ReadyState != WebSocketState.Closed)
            {
                IsConnected = false;
                _cancellationTokenSource?.Dispose();
            }
        }
        
        /// <summary>
        /// 发送命令
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool Send(string msg)
        {
            _webSocket?.Send(msg);
            if (_webSocket == null || !_webSocket.IsAlive)
                return false;

            _logger.LogDebug($"发送到模拟服务数据包：{msg}");
            return true;
        }
        #endregion

        #region 命令
        /// <summary>
        /// 给服务发送心跳包
        /// </summary>
        private void SendHeartBeat()
        {
            if (!IsConnected) return;

            var model = new WebSocketMessageBase<int>
            {
                Code = DataCommonEnum.ManagerHeatBeat
            };

            Send(JsonConvert.SerializeObject(model));
        }
        /// <summary>
        /// 发送培训状态1：开始培训，2：结束培训3：暂停培训
        /// </summary>
        /// <param name="TrainingState"></param>
        /// <returns></returns>
        public bool SendTrainingState(int TrainingState)
        {
            try
            {
                if (!IsConnected)
                    return false;

                var model = new WebSocketMessageBase<int>
                {
                    Code = DataCommonEnum.ManagerTrainingState
                };

                return Send(JsonConvert.SerializeObject(model));
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion
    }
}
